home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Night Owl 6
/
Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso
/
049a
/
send_100.zip
/
SENDNET.C
next >
Wrap
C/C++ Source or Header
|
1991-02-16
|
18KB
|
581 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <dir.h>
#include <dos.h>
#include <io.h>
#include <conio.h>
#include <time.h>
#define MAX_FILENAME_LENGTH 256
#define MAX_LINE_LENGTH 1024
typedef
struct FIDO_message_attribute_struct
{
unsigned Private : 1;
unsigned Crash : 1;
unsigned Recd : 1;
unsigned Sent : 1;
unsigned FileAttached : 1;
unsigned InTransit : 1;
unsigned Orphan : 1;
unsigned KillSent : 1;
unsigned Local : 1;
unsigned HoldForPickup : 1;
unsigned Direct : 1;
unsigned FileRequest : 1;
unsigned ReturnReceiptRequest : 1;
unsigned IsReturnReceipt : 1;
unsigned AuditRequest : 1;
unsigned FileUpdateReq : 1;
} FIDO_message_attrib_type;
typedef
struct FIDO_message_struct
{
char fromUserName[36];
char toUserName[36];
char subject[72];
char dateTime[20];
unsigned timesRead;
unsigned destNode;
unsigned origNode;
unsigned cost;
unsigned origNet;
unsigned destNet;
unsigned destZone;
unsigned origZone;
unsigned destPoint;
unsigned origPoint;
unsigned replyTo;
FIDO_message_attrib_type Attribute;
unsigned nextReply;
char text[1];
} FIDO_message_type;
typedef
FIDO_message_type * FIDO_message_ptr_type;
typedef
struct node_list_struct
{
struct node_list_struct * next;
unsigned zone;
unsigned net;
unsigned node;
unsigned point;
char name[1];
} node_list_type;
typedef node_list_type * node_list_ptr_type;
typedef
struct address_struct
{
unsigned zone;
unsigned net;
unsigned node;
unsigned point;
char name[1];
} address_type;
typedef address_type * address_ptr_type;
void add_to_list(char * buf,
char * file,
unsigned line);
void * allocate_memory(unsigned n_bytes);
unsigned get_highest_message_number(char *area);
void initialize(unsigned argc,
char * argv[]);
void load_bad_message_table(void);
address_ptr_type parse_node_address(char * c,
char * file,
unsigned line);
void parse_parms(unsigned argc,
char * argv[]);
void process_to_file(char * file);
void send_net_mail(char * file);
char * starts_with(char * buf,
char * pat);
char area[MAX_FILENAME_LENGTH];
struct ffblk ff_blk;
unsigned message_number;
char * month[] = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
unsigned n_clusters;
node_list_ptr_type to_list;
node_list_ptr_type to_list_end;
void main (unsigned argc,
char * argv[])
{
unsigned i;
initialize(argc, argv);
for (i=1; i<argc; i++)
if (strnicmp(argv[i], "-f", 2) == 0)
send_net_mail(&argv[i][2]);
exit(0);
}
void add_to_list(char * buf,
char * file,
unsigned line)
{
address_ptr_type address;
node_list_ptr_type entry;
char * name;
if ((name = starts_with(buf, "To:")) == NULL)
{
fprintf(stderr, "Error: Missing \"To\" address on line %u in file \"%s\".\n",
line, file);
exit(1);
};
address = parse_node_address(name, file, line);
entry = (node_list_ptr_type) allocate_memory(sizeof(node_list_type) +
strlen(address->name));
entry->zone = address->zone;
entry->net = address->net;
entry->node = address->node;
entry->point = address->point;
strcpy(entry->name, address->name);
free(address);
if (to_list_end == NULL)
to_list =
to_list_end = entry;
else
{
to_list_end->next = entry;
to_list_end = entry;
};
return;
}
void * allocate_memory(unsigned n_bytes)
{
void * buffer;
if ((buffer = malloc(n_bytes)) == NULL)
{
fprintf(stderr, "Error: Out of memory.\n");
exit(1);
};
memset(buffer, 0, n_bytes);
return(buffer);
}
unsigned get_highest_message_number(char *area)
{
unsigned done;
char file[MAX_FILENAME_LENGTH];
unsigned highest_message_number;
unsigned i;
strcpy(file, area);
strcat(file, "*.msg");
highest_message_number = 0u;
done = findfirst(file, &ff_blk, FA_RDONLY|FA_HIDDEN|FA_SYSTEM|FA_DIREC);
while (!done)
{
*strrchr(ff_blk.ff_name, '.') = '\000';
i = atoi(ff_blk.ff_name);
if (i > highest_message_number)
highest_message_number = i;
done = findnext(&ff_blk);
};
return(highest_message_number+1u);
}
void initialize(unsigned argc,
char * argv[])
{
to_list =
to_list_end = NULL;
strcpy(area,"");
if (argc < 2u)
{
fprintf(stderr, "\n\n\n\n\n");
fprintf(stderr, "Function: SendNet sends NetMail to lists of recepients.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Usage: SendNet -a<NetDir> -f<MsgFile>...\n");
fprintf(stderr, " Where: <NetDir> is the NetMail directory.\n");
fprintf(stderr, " <MsgFile> is a file containing the message to be sent.\n");
fprintf(stderr, "\n");
fprintf(stderr, "Each message file has the following line format.\n");
fprintf(stderr, " To: <name> @ <address> ---+\n");
fprintf(stderr, " . . . . . | At least one recepient must\n");
fprintf(stderr, " To: <name> @ <address> | be specified. The To and @To\n");
fprintf(stderr, " [@To: <to_list_file>] | lines may be in any order.\n");
fprintf(stderr, " . . . . . |\n");
fprintf(stderr, " [@To: <to_list_file>] ---+\n");
fprintf(stderr, " From: <name> @ <address>\n");
fprintf(stderr, " [Subject: <subject text>]\n");
fprintf(stderr, " [Attribute: [Audit] [Crash | Direct | Hold] [KillSent] [Receipt]]\n");
fprintf(stderr, " [@Include: <file where message text is continued]\n");
fprintf(stderr, " <message text>\n");
fprintf(stderr, " . . . . .\n");
fprintf(stderr, " <message text>\n");
fprintf(stderr, "Note: Blank lines must separate paragraphs.\n");
exit(1);
};
fprintf(stderr, "Send NetMail Utility. Written by David Troendle (1:396/5).\n");
fprintf(stderr, "Tested, documented and distributed by John Souvestre (1:396/1).\n");
fprintf(stderr, "Version 1.00, February 12, 1991.\n");
fprintf(stderr, "\n");
parse_parms(argc, argv);
message_number = get_highest_message_number(area);
return;
}
address_ptr_type parse_node_address(char * c,
char * file,
unsigned line)
{
address_ptr_type address;
char ch;
char * name;
char * node;
if ((node = strchr(c, '@')) == NULL)
{
fprintf(stderr, "Error: Missing network address on line %u in file \"%s\".\n",
line, file);
exit(1);
};
name = c;
c = node++;
*c = ' ';
while (*c == ' ')
c--;
*++c = '\000';
address = (address_ptr_type) allocate_memory(sizeof(address_type) +
strlen(name));
strcpy(address->name, name);
while (*node == ' ')
node++;
c = node;
while (isdigit(*c))
c++;
if (*c == ':')
{
*c++ = '\000';
address->zone = atoi(node);
node = c;
while (isdigit(*c))
c++;
};
if (*c == '/')
{
*c++ = '\000';
address->net = atoi(node);
node = c;
while (isdigit(*c))
c++;
}
else
{
fprintf(stderr, "Error: Invalid network address on line %u in file \"%s\".\n",
line, file);
exit(1);
};
ch = *c;
*c++ = '\000';
address->node = atoi(node);
if (ch == '.')
{
node = c;
while (isdigit(*c))
c++;
address->point = atoi(node);
};
return(address);
}
void parse_parms(unsigned argc,
char * argv[])
{
unsigned i;
for (i=1; i<argc; i++)
{
if (strnicmp(argv[i], "-a", 2) == 0)
{
if (strlen(area) > 0)
{
fprintf(stderr, "Error: \"-a\" switch can only appear once.\n");
exit(1);
};
strcpy(area, &argv[i][2]);
continue;
};
if (strnicmp(argv[i], "-f", 2) == 0)
continue;
fprintf(stderr, "Error: Unknown switch: \"%s\".\n", argv[i]);
exit(1);
};
if (strlen(area) == 0)
{
fprintf(stderr, "Error: \"-a\" switch missing or null.\n");
exit(1);
};
if (area[strlen(area) - 1] != '\\')
strcat(area, "\\");
return;
}
void process_to_file(char * file)
{
char buf[MAX_LINE_LENGTH];
FILE * infile;
unsigned line;
if ((infile = fopen(file, "r")) == NULL)
{
fprintf(stderr, "Error: Could not open \"To\" file: \"%s\".\n", file);
exit(1);
};
line = 0u;
while (fgets(buf, MAX_LINE_LENGTH, infile))
{
line++;
if (strlen(buf) == 1)
continue;
add_to_list(buf, file, line);
};
fclose(infile);
return;
}
void send_net_mail(char * file)
{
address_ptr_type address;
char buf[MAX_LINE_LENGTH];
char * c;
node_list_ptr_type entry;
unsigned eof;
unsigned first_line;
char fn[MAX_FILENAME_LENGTH];
FILE * infile;
unsigned len;
unsigned line;
char * mp;
FIDO_message_ptr_type msg;
unsigned n_bytes;
char * name;
FILE * outfile;
char outfile_name[MAX_FILENAME_LENGTH];
struct tm * tblock;
time_t timer;
msg = (FIDO_message_ptr_type) allocate_memory(65530u);
strcpy(fn, file);
if ((infile = fopen(fn, "r")) == NULL)
{
fprintf(stderr, "Error: Could not open message file \"%s\".\n", fn);
exit(1);
};
memset(msg, 0, 65530u);
n_bytes = sizeof(FIDO_message_type) - 1u;
mp = msg->text;
line = 0u;
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
while (!eof)
{
if ((c = starts_with(buf, "@To:")) != NULL)
{
buf[strlen(buf)-1] = '\000';
process_to_file(c);
}
else
{
if ((c = starts_with(buf, "To:")) != NULL)
add_to_list(buf, file, line);
else
break;
};
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
};
if ((name = starts_with(buf, "From:")) == NULL)
{
fprintf(stderr, "Error: Missing \"From\" address on line %u in file \"%s\".\n",
line, fn);
exit(1);
};
address = parse_node_address(name, fn, line);
memset(msg->fromUserName, 0, 36);
strncpy(msg->fromUserName, address->name, 35);
msg->origZone = address->zone;
msg->origNet = address->net;
msg->origNode = address->node;
msg->origPoint = address->point;
free(address);
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
if (!eof && ((name = starts_with(buf, "subject:")) != NULL))
{
while (*name == ' ')
name++;
if ((c = strrchr(buf, '\n')) != NULL)
*c = '\000';
memset(msg->subject, 0, 72);
strncpy(msg->subject, name, 71);
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
}
else
{
strcpy(msg->subject, "Message generated by SendNet");
};
if (!eof && ((name = starts_with(buf, "attribute:")) != NULL))
{
strlwr(buf);
if (strstr(buf, "audit"))
msg->Attribute.AuditRequest = 1u;
if (strstr(buf, "crash"))
msg->Attribute.Crash = 1u;
if (strstr(buf, "Direct"))
msg->Attribute.Direct = 1u;
if (strstr(buf, "hold"))
msg->Attribute.HoldForPickup = 1u;
if (strstr(buf, "killsent"))
msg->Attribute.KillSent = 1u;
if (strstr(buf, "receipt"))
msg->Attribute.ReturnReceiptRequest = 1u;
if ((msg->Attribute.Crash +
msg->Attribute.Direct +
msg->Attribute.HoldForPickup) > 1)
{
fprintf(stderr, "Error: Conflict between Crash/Direct/Hold on line %u in file \"%s\".\n",
line, fn);
exit(1);
};
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
};
msg->Attribute.Local = 1u;
msg->Attribute.Private = 1u;
if (!eof && ((name = starts_with(buf, "@include:")) != NULL))
{
while (*name == ' ')
name++;
fclose(infile);
if ((c = strrchr(name, '\n')) != NULL)
*c = '\000';
if (strlen(name) >= MAX_FILENAME_LENGTH)
{
fprintf(stderr, "Error: Invalid include file name \"%s\" on line %u in file \"%s\".\n",
name, line, fn);
exit(1);
};
strcpy(fn, name);
if ((infile = fopen(fn, "r")) == NULL)
{
fprintf(stderr, "Error: Could not open include file \"%s\".\n", fn);
exit(1);
};
line = 0u;
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
};
first_line = 1u;
while (!eof)
{
if ((c = strrchr(buf, '\n')) == NULL)
{
fprintf(stderr, "Error: Message line too long on line %u in file \"%s\".\n",
line, fn);
exit(1);
};
*c = '\r' | 0x80;
if ((len = strlen(buf)) == 1)
*c &= 0x7f;
if ((len == 1) && !first_line)
*(mp-1) &= 0x7f;
if ((*(mp-1) == ((char) 0x8d)) && !first_line)
{
*(mp-1) = ' ';
*mp++ = 0x8d;
n_bytes++;
};
first_line = 0u;
if (n_bytes > (65530u - len))
{
fprintf(stderr, "Error: Message too long on line %u in file \"%s\".\n",
line, fn);
exit(1);
};
strcat(mp, buf);
mp += len;
n_bytes += len;
eof = fgets(buf, MAX_LINE_LENGTH, infile) == NULL;
if (!eof)
line++;
};
fclose(infile);
for (entry = to_list; entry; entry = entry->next)
{
sprintf(outfile_name, "%s%u.Msg", area, message_number++);
memset(msg->toUserName, 0, 36);
strncpy(msg->toUserName, entry->name, 35);
msg->destZone = entry->zone;
msg->destNet = entry->net;
msg->destNode = entry->node;
msg->destPoint = entry->point;
timer = time(NULL);
tblock = localtime(&timer);
sprintf(msg->dateTime, "%02u %3s %02u %02u:%02u:%02u",
tblock->tm_mday,
month[tblock->tm_mon],
tblock->tm_year,
tblock->tm_hour,
tblock->tm_min,
tblock->tm_sec);
if ((outfile = fopen(outfile_name, "wb")) == NULL)
{
fprintf(stderr, "Error: Could not open \"%s\" for output.\n", outfile_name);
exit(1);
};
fwrite(msg, n_bytes, 1, outfile);
fclose(outfile);
printf("File \"%s\" sent to %s at ", file, msg->toUserName);
if (msg->destZone)
printf("%u:", msg->destZone);
printf("%u/%u", msg->destNet, msg->destNode);
if (msg->destPoint)
printf(".%u", msg->destPoint);
printf("\n in message %s\n", outfile_name);
};
free(msg);
return;
}
char * starts_with(char * buf,
char * pat)
{
char * c;
unsigned len;
c = buf;
len = strlen(pat);
while (*c == ' ')
c++;
if (strnicmp(c, pat, len) == 0)
{
c += len;
while (*c == ' ')
c++;
return(c);
}
else
return(NULL);
}